#pragma once
#include "DXAMLCommon.h"
#include "CDependencyObject.h"
#include "xchainedmap.h"
#include "IATarget.h"
#include "IACounters.h"

class CTimeline;
class CRenderTarget;
class CAnimation;

class CTimeManager :
	public CDependencyObject
{

public: 
	static HRESULT Create(CCoreServices * pCore, struct IPALTickableClock * pIClock, CTimeManager * * ppObject);
	HRESULT Tick(XUINT32 newTimelinesOnly, XUINT32 processIATargets, struct IFrameScheduler * pFrameScheduler);
	XINT32 IsRunning();
	void Reset();
	HRESULT AddTimeline(CTimeline * pTimeline);
private: 
	HRESULT RemoveTimeline(CTimeline * pTimeline, struct TimelineListNode * pPrevNode);
public: 
	HRESULT RemoveTimeline(CTimeline * pTimeline);
	CTimeline * GetRootTimeline();
	XFLOAT GetEstimatedNextTickTime() const;
	XFLOAT GetLastTickTime() const;
	HRESULT CloneForTarget(CRenderTarget * pTarget, CTimeManager * * ppTimeManager);
	HRESULT SetAnimationOnProperty(CWeakRef * pDOWeakRef, XUINT32 nPropertyIndex, CAnimation * pAnimation);
	HRESULT GetAnimationOnProperty(CDependencyObject * pDOWeakRef, XUINT32 nPropertyIndex, CAnimation * * ppAnimation);
	HRESULT GetAnimationOnProperty(CWeakRef * pDOWeakRef, XUINT32 nPropertyIndex, CAnimation * * ppAnimation);
	XUINT32 HasActiveTimelines();
	XUINT32 HasActiveAnimations();
	HRESULT CompleteTopLevelStoryboards();
	XUINT32 IsPrimaryTimeManager();
	XUINT32 CloneNeedsUpdate();
	XUINT32 ShouldCollectIATargets();
	HRESULT CollectIATargets(const xvector<IATarget> * pTargets);
	HRESULT UpdateIATargets();
	void SetIndependentStartTimes();
	void NotifyIndependentAnimationChange();

private: 
	CTimeManager(CCoreServices * pCore, struct IPALTickableClock * pIClock);
	virtual ~CTimeManager();
	static const XUINT32 nHashSize;
	struct HashNode
	{
	public: 
		CWeakRef * pDOWeakRef;
		XUINT32 nPropertyIndex;
		CAnimation * pAnimation;
		HashNode();
		~HashNode();

	};
	XUINT32 Hash(CWeakRef * pDOWeakRef, XUINT32 nPropertyIndex);

	struct TimelineListNode
	{
	public: 
		TimelineListNode();
		~TimelineListNode();
		CTimeline * m_pTimeline;
		struct CTimeManager::TimelineListNode * m_pNext;

	};
	void DeleteTimelineList(struct CTimeManager::TimelineListNode * pNode);
	void UpdateIATarget(XUINT32 prevFrameCount, XUINT32 thisFrameCount, CUIElement * pTarget, enum IndependentAnimationType::Value animType);
	static void ClearTargetMap(xchainedmap<CWeakRef *,IACounters> * pMap);
	XUINT32 m_isPrimaryTimeManager:1;
	XUINT32 m_isLoaded:1;
	XUINT32 m_processIATargets:1;
	XUINT32 m_independentTimelinesChanged:1;
	struct IPALTickableClock * m_pIClock;
	XDOUBLE m_rTimeStarted;
	XDOUBLE m_rLastTickTime;
	struct CTimeManager::TimelineListNode * m_pTimelineListHead;
	struct CTimeManager::TimelineListNode * m_pTimelinePreviousHead;
	CTimeline * m_pRootTimeline;
	CXcpList<CTimeManager::HashNode> * * m_ppHashTable;
	xchainedmap<CWeakRef *,IACounters> * m_pPendingIACounters;
	xchainedmap<CWeakRef *,IACounters> * m_pProcessedIACounters;


};